from mininet.net import Mininet
from mininet.node import Controller, RemoteController, OVSController
from mininet.node import CPULimitedHost, Host, Node
from mininet.node import OVSKernelSwitch, UserSwitch
from mininet.node import IVSSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.link import TCULink, Intf
from subprocess import call
import time
import mininet.util


def myNetwork():
    """
               s5 ---
               |      |
        h1 --- s1 --- s2 --- h2
               |      |
        h3 --- s3 --- s4 --- h4
    """

    net = Mininet( topo=None,
                   build=False,
                   ipBase='10.0.0.0/8',
                   switch=UserSwitch,
                   link=TCULink,
                   autoSetMacs=True, autoStaticArp=True)

    info('*** Adding controller\n')
    c0=net.addController(name='c0',
                         controller=RemoteController,
                         ip='127.0.0.1',
                         protocol='tcp',
                         port=6633)

    info('*** Add switches\n')
    s1 = net.addSwitch('s1')
    s2 = net.addSwitch('s2')
    s3 = net.addSwitch('s3')
    s4 = net.addSwitch('s4')
    s5 = net.addSwitch('s5')

    info('*** Add hosts\n')
    h1 = net.addHost('h1', cls=Host, ip='10.0.0.1', mac='00:00:00:00:00:01', defaultRoute=None)
    h2 = net.addHost('h2', cls=Host, ip='10.0.0.2', mac='00:00:00:00:00:02', defaultRoute=None)
    h3 = net.addHost('h3', cls=Host, ip='10.0.0.3', mac='00:00:00:00:00:03', defaultRoute=None)
    h4 = net.addHost('h4', cls=Host, ip='10.0.0.4', mac='00:00:00:00:00:04', defaultRoute=None)

    info('*** Add links\n')
    net.addLink(s1, h1, 1, bw=12)
    net.addLink(s2, h2, 1, bw=12)
    net.addLink(s3, h3, 1, bw=5)
    net.addLink(s4, h4, 1, bw=5)

    net.addLink(s1, s2, 2, 2, bw=4)
    net.addLink(s1, s3, 3, 2, bw=4)
    net.addLink(s1, s5, 4, 2, bw=4)
    
    net.addLink(s2, s4, 3, 2, bw=4)
    net.addLink(s2, s5, 4, 3, bw=4)
    
    net.addLink(s3, s4, 3, 3, bw=4)
    

    info('*** Starting network\n')
    net.build()
    info('*** Starting controllers\n')
    c0.start()
    info('*** Starting switches\n')
    s1.start([c0])
    s2.start([c0])
    s3.start([c0])
    s4.start([c0])
    s5.start([c0])

    info("Dump all connections in network:\n")
    mininet.util.dumpNetConnections(net)

    info('*** Post configure switches and hosts\n')
    time.sleep(2)
    s1.cmd('sh ./rules/s1')
    s2.cmd('sh ./rules/s2')
    s3.cmd('sh ./rules/s3')
    s4.cmd('sh ./rules/s4')
    s5.cmd('sh ./rules/s5')

    
    h4.cmd('iperf -u -s -p 5566 -i 0.5 > h4server.log &')
    h3.cmd('iperf -u -c 10.0.0.4 -b 3M -p 5566 -t 100 &')

    while True:
        print('please input custom control cmd:\nt: send tcp; u: send udp; c: cli')
        cmd = raw_input()
        if cmd == 't':
            h2.cmd('iperf -s -p 5566 -i 0.5 > h2server.log &')
            h1.cmd('iperf -c 10.0.0.2 -p 5566 -t 20 &')
            time.sleep(5)
            net.configLinkStatus('s1','s2','down')
            time.sleep(0.05)
            net.configLinkStatus('s1','s2','up')
            time.sleep(5)
        if cmd == 'u':
            h2.cmd('iperf -u -s -p 5566 -i 0.5 > h2server.log &')
            h1.cmd('iperf -u -c 10.0.0.2 -b 3M -p 5566 -t 20 &')
            time.sleep(5)
            net.configLinkStatus('s1','s2','down')
            time.sleep(0.05)
            net.configLinkStatus('s1','s2','up')
            time.sleep(5)
        elif cmd == 'c':
            CLI(net)
        else:
            break
    net.stop()

if __name__ == '__main__':
    # setLogLevel( 'debug' )
    myNetwork()
